import re


class Template(object):
    """
    模板，可以解析变量值，解析循环和判断
    """

    def __init__(self, template_param, obj, context):
        """
        :param template_param: 模板文字
        :param obj: 要替换的文字
        :param context: 上下文函数，所有调用的函数必须这样传进去
        :return: 模板对象
        """
        self.template = template_param
        self.obj = obj
        self.context = context
        self.tokens = re.split(r"({{.*?}}|{%.*?%}|{#.*?#})", template_param)

    def compile(self):
        """
        编译模板，将值填入模板
        :return: 编译后的模板
        """
        buffer = []
        for w in self.tokens:
            if w.startswith("{{"):
                exp = w[2: -2].strip()
                buffer.append(self._expr_code(exp))
            elif w.startswith("{%"):
                pass
            else:
                if w:
                    buffer.append(w)
        return "".join(buffer)

    def _expr_code(self, expr):
        """
        获取变量表达式的函数
        :param expr: 解析的表达式
        :return: 解析后的值
        """
        if "|" in expr:
            pipes = expr.split("|")
            code = pipes[0]
            value = self._get_dot_value(code.split("."))
            r = self.context.get(pipes[1])(value)
            return r
        elif "." in expr:
            dots = expr.split(".")
            return self._get_dot_value(dots)

    def _get_dot_value(self, dots):
        """
        获取数据字典"."点内的内容
        :param dots: 解析点后的列表
        :return: 取到的最后的值
        """
        value = self.obj
        for d in dots:
            value = value.get(d)
        return value


if __name__ == '__main__':
    templateStr = """
        <p>{{user.name}}</p>
        <p>{{test|upper}}</p>
    """
    result = Template(templateStr, {
        "user": {
            "name": "xiejingyang"
        },
        "test": "hehe"
    }, {"upper": str.upper}).compile()
    print(result)
